package smlab.media
{
	import flash.display.Sprite;
	import flash.events.AsyncErrorEvent;
	import flash.events.NetStatusEvent;
	import flash.events.SecurityErrorEvent;
	import flash.events.TimerEvent;
	import flash.media.SoundTransform;
	import flash.media.Video;
	import flash.net.NetConnection;
	import flash.net.NetStream;
	import flash.utils.Timer;
	
	import smlab.utils.Trace_SM;
	import smlab.view.ui.UIManager_SM;
	
	/**
	 * 简单 FLV 视频播放器
	 * 只具备如下功能：
	 * 设置视频宽高
	 * 加载完成后从头播放直至结束（无法快进和后退）
	 * 没有音量控制
	 * @author weiwei_zhang
	 * 
	 */
	public class SimpleFLVPlayer extends Sprite
	{
		private var netConnection:NetConnection;
		private var video:Video;
		private var videoContainer:Sprite;
		private var stream:NetStream;
		private var _soundTransform:SoundTransform;
		private var videoURL:String="";
		private var _videWidth:Number=800;
		private var _videHeight:Number=600;
		private var _bufferTime:Number=5;//缓冲时间
		private var _isPlayImmediately:Boolean=false;//是否立刻开始播放（如果 false 则加载完后播放）
		private var _videoLoadedFun:Function=null;
		private var _playOverFun:Function=null;
		private var _playStartFun:Function=null;
		private var timer:Timer;//视频时间总长度（秒）
		
		public function SimpleFLVPlayer()
		{
			super();
			
			init();
		}
		
		private function init():void
		{
			videoContainer=new Sprite;
			addChild(videoContainer);
			
			netConnection=new NetConnection();
			netConnection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
			netConnection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
			
			timer=new Timer(200);
			timer.addEventListener(TimerEvent.TIMER,onTimer);
		}
		
		/**
		 * 
		 * @param flvURL				视频路径
		 * @param isPlayImmediately		是否立刻开始播放（如果 false 则加载完后播放），超兽游戏默认为 false
		 * @param playOverFun			播放完毕的时候调用的方法（播放出错或加载出错或者关掉视频也会调用）
		 * @param bufferTime			缓冲时间（尽在 isPlayImmediately = true 时有效）
		 * @param videoLoadedFun		视频加载完毕以及开始播放的时候调用的方法
		 * 
		 */
		public function play(flvURL:String,isPlayImmediately:Boolean=false,playOverFun:Function=null,playStartFun:Function=null,bufferTime:Number=5,videoLoadedFun:Function=null):void
		{
			videoURL=flvURL;
			_isPlayImmediately=isPlayImmediately;
			_bufferTime=bufferTime;
			_videoLoadedFun=videoLoadedFun;
			_playOverFun=playOverFun;
			_playStartFun=playStartFun;
			
			netConnection.connect(null);
		}
		
		public function set videoWidth(w:Number):void
		{
			_videWidth=w;
		}
		
		public function get videoWidth():Number
		{
			return _videWidth;
		}
		
		public function set videoHeight(h:Number):void
		{
			_videHeight=h;
		}
		
		public function get videoHeight():Number
		{
			return _videHeight;
		}
		
		private function netStatusHandler(e:NetStatusEvent):void{
			switch(e.info.code){
				case "NetConnection.Connect.Success":
					connectStream();
					break;
				case "NetStream.Play.StreamNotFound":
					Trace_SM.trace("无法找到视频流");
					playOverOrError();
					break;
				case "NetStream.Play.Failed":
					Trace_SM.trace("无法播放该视频");
					playOverOrError();
					break;
				case "NetStream.Play.Start":
					
					Trace_SM.trace("视频开始播放:"+videoURL);
					stream.pause();
					resize();
					break;
				case "NetStream.Play.Stop":
					Trace_SM.trace("视频停止播放");
					playOverOrError();
					break;
				case "NetStream.Buffer.Full":
//					Trace_SM.trace("视频缓冲已满");
					break;
				case "NetStream.Buffer.Empty":
//					Trace_SM.trace("视频缓冲已空");
					break;
			}
		}
		
		private function connectStream():void
		{
			addEventAndTryPlay();
			
			if(videoURL && videoURL !="")
			{
				stream.play(videoURL);
				timer.start();
			}else{
				Trace_SM.trace("视频 URL 为空！");
			}
		}
		
		private function onTimer(e:TimerEvent):void
		{
			UIManager_SM.getInstance().loadingPanel.setPercent(stream.bytesLoaded,stream.bytesTotal,"正在加载视频");
			
			if(stream.bytesLoaded>0 && stream.bytesLoaded == stream.bytesTotal){
				timer.stop();
				timer.removeEventListener(TimerEvent.TIMER,onTimer);
				stream.resume();
				Trace_SM.trace("视频加载已完成，继续播放");
				
				runPlayStartFun();
				runLoadedFun();
			}
			
			if(timer.repeatCount>1800){
				Trace_SM.trace("视频加载超时（30分钟），结束播放");
				removeAll();
			}
		}
		
		private function addEventAndTryPlay():void 
		{
			Trace_SM.trace("尝试加载并播放视频……");
			
			removeStream();
			stream=new NetStream(netConnection);
			stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
			stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
			stream.checkPolicyFile=false;
			stream.bufferTime = _bufferTime;
			
			_soundTransform = new SoundTransform;
			_soundTransform.volume=1;
			stream.soundTransform=_soundTransform;
			
			video=new Video(videoWidth,videoHeight);
			video.attachNetStream(stream);
			videoContainer.addChild(video);
			
			var customClient:Object = new Object();
			customClient.onMetaData = onMetaDataHandler;
			customClient.onImageData = onImageDataHandler;
			customClient.onPlayStatus = onPlayStatusHandler;
			stream.client = customClient;
		}
		
		private function resize():void{
			video.width=videoWidth;
			video.height=videoHeight;
			videoContainer.graphics.clear();
			videoContainer.graphics.beginFill(0xffffff,0.3);
			videoContainer.graphics.drawRect(0,0,videoWidth,videoHeight);
			videoContainer.graphics.endFill();
		}
		
		/**
		 * 获得加载进度等信息
		 * @param data
		 * 
		 */
		private function onMetaDataHandler(data:Object):void {
			Trace_SM.trace("视频已加载："+int(stream.bytesLoaded/stream.bytesTotal)*100+"%");
			Trace_SM.trace("视频总时长（秒）："+data.duration+"，帧速（帧/秒）："+data.framerate);
		}
		
		private function onImageDataHandler(imageData:Object):void {
			Trace_SM.trace("SimpleFLVPlayerImageData: " + imageData.data.length);
		}
		
		private function onPlayStatusHandler(info:Object):void {
			Trace_SM.trace("onPlayStatusHandler"+info);
		}
		
		private function securityErrorHandler(e:SecurityErrorEvent):void{
			Trace_SM.trace("securityErrorHandler"+e);
		}
		
		private function asyncErrorHandler(e:AsyncErrorEvent):void{
			Trace_SM.trace("asyncErrorHandler"+e);
		}
		
		private function runPlayStartFun():void 
		{
			UIManager_SM.getInstance().loadingPanel.hide();
			
			if(_playStartFun!=null){
				_playStartFun();
				_playStartFun=null;
			}
		}
		
		private function runLoadedFun():void 
		{
			if(_videoLoadedFun!=null){
				_videoLoadedFun();
				_videoLoadedFun=null;
			}
		}
		
		private function playOverOrError():void
		{
			if(_playOverFun!=null){
				_playOverFun();
				_playOverFun=null;
				removeAll();
			}
		}
		
		private function removeStream():void 
		{
			if(stream){
				stream.removeEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
				stream.removeEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
				stream.close();
				stream=null;
			}
		}
		
		/**
		 * 内存回收
		 * 
		 */
		public function removeAll():void
		{
			removeStream();
			
			if(timer){
				timer.removeEventListener(TimerEvent.TIMER,onTimer);
				timer=null;
			}
			
			if(netConnection){
				netConnection.removeEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
				netConnection.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
				netConnection.close();
				netConnection=null;
			}
			
			video=null;
			videoContainer=null;
			_soundTransform=null;
			_videoLoadedFun=null;
			_playOverFun=null;
		}
	}
}